﻿/*Copyright (C) 2011 by Marcin Kozlowski (naarkie@gmail.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace VillageOfAres
{
    class Program
    {
        static int money = 150;
        static int population = 1;
        static int food = 100;
        static int warriors = 0;
        static int maxpeepsperhouse = 5; //determines how many people can be in a house max.
        static int houses = 3; //if theres more, the village is 'overpopulated'.
        static int farms = 0;
        static string villageName = "Derp";
        static string[] commands = { 
        "attack - Attack a village. Usage: 'attack VillageName' OR 'attack VillageID'",
        "build - Build a building. Usage: 'build BuildingName'.",
        "endturn - Ends your turn.","villages - Lists all enemy villages." };
        //descriptions for each command.
        //Huuur this is ugleh. Should make a neater way. Not sure how. Meh.
        static string[] consolecommand;
        public static int turn = 0;
        static int taxIncome;
        static bool buildingSomething = false;
        static bool canAttack = true; //is an attack already in progress?
        static bool buildingFarm = false;
        static int attackTurnsLeft = 3;
        static int buildTurnsLeft = 3;
        static public Generator generator;
        static public int difficultyTimer = 0;
        public enum Difficulty
        {
            Easy,
            Medium,
            Hard,
            IMPOSSIBLARG
        }
        public static Difficulty difficulty = new Difficulty();
        static List<Village> villages = new List<Village>();
        static Event _event = new Event();
        Random rng = new Random();


        private static void SetColor(ConsoleColor color)
        {
            Console.ForegroundColor = color;
        }

        private static void Write(string text)
        {
            Console.Write(text);
            //Well its faster than typing Console.WriteLine

        }

        private static void EndTurn()
        {
            taxIncome = 2 * population;
            food += farms * 10;
            //give moneys and fuds to own village
            turn++;
            money+=taxIncome;
            if (buildingSomething == true)
            {
                buildTurnsLeft -= 1; //if you're building something
                //decrease the build turn left counter
            }
            if (canAttack == false)
            {
                attackTurnsLeft -= 1; //if you're building something
                //decrease the build turn left counter
            }
            _event.Check();

            //At the end of each turn, give food and money to other villages as well.
            //Also, build warriors and people as neccesarry (gosh i hate the spelling of that word)
            Random rng = new Random();
            foreach (Village village in villages)
            {
                village.food += rng.Next(10);
                village.gold += village.population * 2;

                if (village.gold > 50)
                {
                    village.warriors += 1;
                    village.gold -= 50;
                }
                if (village.food > 50)
                {
                    village.population += 1;
                    village.food -= 50;
                }
                if (village.population < 0)
                {
                    village.population = 0;
                }
            }

            Idle();

        }

        private static void Idle()
        {
            SetColor(ConsoleColor.Gray);
            Console.BackgroundColor = ConsoleColor.Black;
            Console.Clear();
            #region events
            if (_event.isPanda == true)
            {
                money = money-(money / 4);
                food = food-(food / 4); //what is this i dont even.
                // *drool*
                //oh yes the panda steals a quarter of food and dollaz.
                //because science.
                if ((turn - _event.nowturn <= 2) && (turn > difficultyTimer * 2)) //panda's only attack past turn 20
                {
                    SetColor(ConsoleColor.Red);
                    Write("GIANT PANDA ATTACK\nA giant panda appears!\nOh no, he has taken our food!\n");
                    SetColor(ConsoleColor.Green);
                    Write("The panda has taken ");
                    SetColor(ConsoleColor.Magenta);
                    Write((food - (food / 4)).ToString());
                    SetColor(ConsoleColor.Green);
                    Write(" food and ");
                    SetColor(ConsoleColor.Magenta);
                    Write((money - (money / 4)).ToString());
                    SetColor(ConsoleColor.Green);
                    Write(" gold.\n\n");
                    _event.isPanda = false;
                }
            }
            if (_event.isAttacked)
            {
                Random random = new Random();
                int index = random.Next(0, villages.Count);
                Village village2 = villages.ElementAt(index);
                if ((village2.warriors > warriors) && (turn > difficultyTimer)) //enemy villages only attack past turn 10
                {
                    if (warriors > 1)
                    {
                        warriors -= (village2.warriors - warriors);
                    }
                    if (food > 20)
                    {
                        food-=20;
                        village2.food += 20;
                    }
                    if (money > 20)
                    {
                        money-=20;
                        village2.gold += 20;
                    }
                    Write("\n\nTerror! Disdain! Misfortune has fallen upon our city,\nas the warriors of ");
                    SetColor(ConsoleColor.Red);
                    Write(village2.name);
                    SetColor(ConsoleColor.Gray);
                    Write(" have attacked!\n\n");
                }
                _event.isAttacked = false;
            }
            if (buildTurnsLeft == 0 && buildingFarm == true)
            {
                SetColor(ConsoleColor.Red);
                Write("Your farm has been built, m'lord.\n\n");
                farms++;
                buildTurnsLeft = 3;
                buildingSomething = false;
            }
            if (attackTurnsLeft == 0 && canAttack == false)
            {
                SetColor(ConsoleColor.Cyan);
                Write("Your warriors have rested and repaired their equipment.\nThey are fit for battle once more.\n\n");
                buildTurnsLeft = 3;
                buildingSomething = false;
            }
            if (population / houses > maxpeepsperhouse)
            {
                SetColor(ConsoleColor.Red);
                Write("!!!WARNING!!!\nYour village is overpopulated!\nYou will lose 10% gold per turn!\n\n");
            }
            SetColor(ConsoleColor.Gray);
            Write("Welcome to village ");
            SetColor(ConsoleColor.Magenta);
            Write(villageName);
            SetColor(ConsoleColor.Gray);
            Write(".\nIt is turn number ");
            SetColor(ConsoleColor.Yellow);
            Write(turn.ToString());
            SetColor(ConsoleColor.Gray);
            Write(".\nYou have:\n\n");
            SetColor(ConsoleColor.Magenta);
            Write(" - " + money + " Gold.\n - " + population + " Person(s).\n - " + houses + " House(s).\n - " + food + " Food.\n - " + warriors + " Warrior(s).\n - " + farms + " Farm(s).");
            SetColor(ConsoleColor.Gray);
            if (turn < 4)
            {
                Write("\nType 'commands' to list all applicable commands\nType 'info' to see info about the village.");
            }
            Write("\n\nWhat is thy bidding?\n\n");
            SetColor(ConsoleColor.Yellow);
            Write(">");
            consolecommand = Console.ReadLine().Split(' ');
            SetColor(ConsoleColor.Gray);
            #endregion

            //MY EYES, THEY BUUUUUUURN
            #region input parsing
            switch (consolecommand[0])
            {
                case "commands":
                    Write("Available commands are:\n");
                    SetColor(ConsoleColor.Green);
                    for(int i = 0;i < commands.Length;i++)
                    {
                        Write(commands[i] + "\n");
                    }
                    Write("\n");
                    Console.ReadKey();
                    Idle();
                    break;
                case "villages":
                    Console.ForegroundColor = ConsoleColor.Green;
                    foreach (Village village in villages)
                    {
                        village.returnName();
                    }
                    Write("\nPress any key to continue.");
                    Console.ReadKey();
                    Idle();
                    break;
                case "cheat":
                    Write("\nCheats enabled.");
                    money += 2000;
                    farms += 15;
                    population += 50;
                    houses += 50;
                    warriors += 100;
                    Console.ReadKey();
                    Idle();
                    break;
                case "info":
                    SetColor(ConsoleColor.DarkCyan);
                    Write("\nProbability of enemy attack: " + _event.attackProbability + "%\n");
                    Write("Probability of plague: " + _event.plagueProbability + "%\n");
                    Write("Probability of Giant Panda attack: " + _event.pandaProbability + "%\n");
                    Console.ReadKey();
                    Idle();
                    break;
                case "attack":
                    foreach (Village village in villages)
                    {
                        try
                        {
                            if (village.name == consolecommand[1] || village.id.ToString() == consolecommand[1])
                            {
                                //thanks to Funley from Facepunch for this
                                //http://www.facepunch.com/threads/1092921?p=32888896&viewfull=1#post32888896
                                if (warriors > 0)
                                {
                                    //oh wow this is a lot of brackets :/
                                    if (warriors > village.warriors)
                                    {
                                            Random rng = new Random();
                                            canAttack = false;
                                            warriors -= rng.Next(village.warriors);
                                            int oldfood = village.food;
                                            food += village.food;
                                            village.food = 0;
                                            int oldgold = village.gold;
                                            money += village.gold;
                                            village.gold = 0;
                                            village.warriors = rng.Next(village.warriors) ;
                                            village.population = rng.Next(village.population);

                                            SetColor(ConsoleColor.Red);
                                            Write("\n\n\nYour warriors arrive just after dawn.\nThey pillaged all night long.\nHowever, we lost some warriors in the battle.");
                                            Write("\n\n" + oldfood + " food taken from " + village.name + ".");
                                            Write("\n" + (rng.Next(village.warriors)) + " of our warriors died in the battle.");
                                            Console.ReadKey();
                                            Idle();
                                    }
                                    else
                                    {
                                        Write("\n\nSadly, your warriors are defeated by the enemy\nTry to attack once your numbers are greater.");
                                        Console.ReadKey();
                                        Idle();
                                    }
                                }
                                else
                                {
                                    Write("\n\nFoo! You have no warriors! How do you expect to kill the enemy?");
                                    Console.ReadKey();
                                    Idle();
                                }
                            }
                            /*else
                            {
                                SetColor(ConsoleColor.DarkRed);
                                Write("\nNo such village found.");
                                Console.ReadKey();
                                Idle();
                            }*/
                        }
                        catch (IndexOutOfRangeException)
                        {
                            SetColor(ConsoleColor.DarkRed);
                            Write("\nNo such village found.");
                            Console.ReadKey();
                            Idle();
                        }

                     }
                   
                    Idle();
                    break;
                case "conquer":
                    for (int i = 0; i < villages.Count; i++)
                    {
                        if (villages[i].name == consolecommand[1] || villages[i].id.ToString() == consolecommand[1])
                        {
                            SetColor(ConsoleColor.Red);
                            Write("\n\nA joyous day!\nOur glorious and powerful village has conquered and demolished " + villages[i].name + ".\nOnly " + (villages.Count - 1) + " villages left to conquer before we achieve supremacy!\n");

                            villages.RemoveAt(i); //remove the conquered village from the list                             
                            i--;
                        }
                    }
                    Console.ReadLine();
                    Idle();
                    break;
                case "endturn":
                        EndTurn();
                    break;
                case "build":
                    try
                    {
                        if (consolecommand[1] == "farm")
                        {
                            if (money >= 150)
                            {
                                money -= 150;
                                buildingFarm = true;
                                buildingSomething = true;
                                Write("Your villagers start building your farm. It will take ");
                                SetColor(ConsoleColor.Magenta);
                                Write(buildTurnsLeft.ToString());
                                SetColor(ConsoleColor.Gray);
                                Write(" turns more to build the farm.");
                                Console.ReadLine();
                                Idle();
                            }
                            else
                            {
                                SetColor(ConsoleColor.Red);
                                Random rng = new Random();
                                int chance = rng.Next(4);
                                if (chance == 1)
                                {
                                    Write("You don't have enough money to build that. A farm costs 150 gold.");
                                }
                                else if (chance == 2)
                                {
                                    Write("COME BACK WHEN MUMMY AND DADDY GIVE YOU SOME POCKET MONEY");
                                }
                                else
                                {
                                    Write("You can't afford that. Go tax your villagers some more.");
                                }
                                Console.ReadLine();
                                Idle();
                            }
                        }
                        else
                        {
                            Write("No such building found.");
                            Console.ReadKey();
                            Idle();
                        }
                    }
                    catch(IndexOutOfRangeException)
                    {
                      Write("No such building found.");
                      Console.ReadKey();
                      Idle();
                    }
                    break;
                case "citizen":
                    if (food >= 50)
                    {
                        SetColor(ConsoleColor.Red);
                        Write("\n\nAt the hands of your ruler, a new citizen joins or mighty village!");
                        population++;
                        food -= 50;
                        Console.ReadKey();
                    }
                    else
                    {
                        Random rng = new Random();
                        int chance = rng.Next(4);
                        SetColor(ConsoleColor.Red);
                        if (chance == 1)
                        {
                            Write("\nLol you're too poor to buy a citizen. Come back when you get a job.");
                        }
                        else if (chance == 2)
                        {
                            Write("\nYour people are already starving, and you want MORE people?! Oh, you're the greatest ruler since Ivan the TERRIBLE");
                        }
                        else
                        {
                            Write("\nYou can't afford that. Go tax your villagers some more.");
                        }
                        Console.ReadKey();
                    }
                    Idle();
                    break;
                case "warrior":
                    if (money >= 50)
                    {
                        SetColor(ConsoleColor.Red);
                        Write("\nA new warrior has been trained!");
                        warriors++;
                        money -= 50;
                        Console.ReadKey();
                    }
                    else
                    {
                        Random rng = new Random();
                        SetColor(ConsoleColor.Red);
                        int chance = rng.Next(4);
                        //IS THIS REAL LIFE!?
                        if (chance == 1)
                        {
                            Write("\nLol you're too poor to buy a warrior. Come back when you get a job.");
                        }
                        else if (chance == 2)
                        {
                            Write("\nCOME BACK WHEN MUMMY AND DADDY GIVE YOU SOME POCKET MONEY");
                        }
                        else
                        {
                            Write("\nYou can't afford that. Go tax your villagers some more.");
                        }
                        Console.ReadKey();
                    }
                    Idle();
                    break;
                default:
                    Write("I don't know that command.");
                    Console.ReadKey();
                    Idle();
                    break;
            }
            #endregion
            //I should probably make some sort of 'official' command system not bloody switch and case statements
            //"If it ain't broken, don't fix it"
            //Oh shut up, you. It looks messy.
            //"Yeah but it works. Are you gonna spend 10 hours making a proper command system that doesnt work?"
            //....
            //TODO: stop having conversations with myself in comments
        }

        ///<summary>
        ///Sets up game at the beggining of game. 
        ///</summary>
        private static void Setup()
        {
            Write("Type your village name: ");
            SetColor(ConsoleColor.Yellow);
            villageName = Console.ReadLine();
            SetColor(ConsoleColor.Gray);
            Console.Clear();
            Write("At what difficulty would you like to play as? 1/2/3/4");
            SetColor(ConsoleColor.Yellow);
            string difnum = Console.ReadLine();
            switch (difnum)
            {
                case "1":
                    difficulty = Difficulty.Easy;
                    SetupGen();
                    break;
                case "2":
                    difficulty = Difficulty.Medium;
                    SetupGen();
                    break;
                case "3":
                    difficulty = Difficulty.Hard;
                    SetupGen();
                    break;
                case "4":
                    difficulty = Difficulty.IMPOSSIBLARG;
                    Write("Are you sure you want to play on IMPOSSIBLARG difficulty?");
                    Console.ReadKey();
                    Console.Clear();
                    SetupGen();
                    break;
                default:
                    Setup();
                    break;
            }
         //commented out because I don't want to set up game each time i run it
         //TODO: also, add difficulty levels
        }

        public static void SetupGen()
        {
            int maxfood = 0;
            int maxwarriors = 0;
            int maxgold = 0;
            int maxpopulation = 0;
            int villAmount = 0;
            switch (difficulty)
            {
                case Difficulty.Easy:
                    maxfood = 100;
                    maxwarriors = 30;
                    maxgold = 150;
                    maxpopulation = 7;

                    villAmount = 2;
                    food = 150;
                    money = 150;
                    houses = 3;
                    difficultyTimer = 10;
                    break;
                case Difficulty.Medium:
                    maxfood = 200;
                    maxwarriors = 50;
                    maxgold = 250;
                    maxpopulation = 12;

                    villAmount = 4;
                    food = 125;
                    money = 110;
                    houses = 3;
                    difficultyTimer = 7;
                    break;
                case Difficulty.Hard:
                    maxfood = 400;
                    maxwarriors = 50;
                    maxgold = 550;
                    maxpopulation = 20;

                    villAmount = 6;
                    food = 75;
                    money = 50;
                    houses = 2;
                    difficultyTimer = 5;
                    break;
                case Difficulty.IMPOSSIBLARG:
                    maxfood = 1000;
                    maxwarriors = 70;
                    maxgold = 850;
                    maxpopulation = 50;

                    villAmount = 10;
                    food = 50;
                    money = 25;
                    houses = 1;
                    difficultyTimer = 2;
                    break;
            }
            generator = new Generator(maxfood, maxwarriors, maxgold, maxpopulation);
            for (int i = 0; i < villAmount; i++)
            {
                villages.Add(generator.GenerateVillage());
                System.Threading.Thread.Sleep(150);
            }
            Write("\n\nGeneration complete.");
            Console.ReadKey();
            Idle();
        }

        static void Main(string[] args)
        {
            Console.SetWindowSize(90, 40);
            Console.Title = "Village of Ares";
            Setup();
            Idle();
            /*Write("Welcome to AWESOME VILLAGE SIMULATOR LOL\nPress any key to start setup.");
            Console.ReadKey();
            Console.Clear();*/
            
        }
    }
}
